package net.animats.music;

import java.util.Map;
import java.util.HashMap;
import java.util.Collection;

public class ScaleType extends IntervalSet {

    private static Map<String, ScaleType> scaleTypes = new HashMap<String, ScaleType>();

    // AN ARRAY THAT INDICATES WHETHER THE NOTES FOR THIS SCALE SHOULD BE CALLED FLAT OR SHARP
    // INDEX 0 INDICATES THE NAMING FOR 'A', AND SO ON
    private int namingConvention[];

    // THE OFFSETS RELATIVE TO THE BASELINE OF THE MAJOR SCALE
    private Integer[] offsets;

    static {
        // CREATE ScaleType USING OFFSETS: -1 = FLAT, +1 = SHARP
        scaleTypes.put("Major", new ScaleType("Major", "Maj",
                // INFORMATION USED FOR NAMING THE KEY AND THE NOTES WITHIN IT
                new int[]{SHARP, FLAT, SHARP, NATURAL, FLAT, SHARP, FLAT, SHARP, FLAT, SHARP, SHARP, FLAT},
                // THE OFFSETS RELATIVE TO THE BASELINE OF THE MAJOR SCALE
                new Integer[]{NATURAL, NATURAL, NATURAL, NATURAL, NATURAL, NATURAL, NATURAL}));
        scaleTypes.put("Minor", new ScaleType("Minor", "m",
                // INFORMATION USED FOR NAMING THE KEY AND THE NOTES WITHIN IT
                new int[]{NATURAL, FLAT, SHARP, FLAT, SHARP, FLAT, SHARP, SHARP, FLAT, SHARP, FLAT, SHARP},
                // THE OFFSETS RELATIVE TO THE BASELINE OF THE MAJOR SCALE
                new Integer[]{NATURAL, NATURAL, FLAT, NATURAL, NATURAL, FLAT, FLAT}));
    }

    private ScaleType(String _name, String _shortName, int[] _namingConvention, Integer[] _offsets) {
        super(_name, _shortName);

        // STORE THE SUPPLIED OFFSETS FOR FUTURE PRESENTATION PURPOSES
        offsets = _offsets;

        // STORE THE SUPPLIED NAMES FOR FUTURE PRESENTATION PURPOSES
        namingConvention = _namingConvention;

        // GENERATE A SET OF INTERVALS FROM THE OFFSETS SUPPLIED
        int[] intervals = new int[7];

        try {
            for (int index = 0; index < 7; index++) {
                addInterval(majorScaleIntervals[index] + offsets[index]);
            }
        } catch (IndexOutOfBoundsException e) {
            System.out.println("Trying to create a ScaleType with insufficient intervals or offsets.");
        }
    }

    public int getNamingIndex(int _rootNote) {
        if (namingConvention[_rootNote] == FLAT) {
            return 1;
        } else {
            return 0;
        }
    }

    public int getNamingIndex(Note _rootNote) {
        if (namingConvention[_rootNote.getNameIndex()] == FLAT) {
            return 1;
        } else {
            return 0;
        }
    }

    public static Collection<ScaleType> getScaleTypes() {
        return scaleTypes.values();
    }

    public String getType() {
        return "{scaleType}";
    }

    public static ScaleType getScaleType(String _name) {
        return scaleTypes.get(_name);
    }

    public static ScaleType getScaleType(NoteSet _noteSet) {
        return getScaleType (_noteSet.getIntervalSet());
    }

    public static ScaleType getScaleType(IntervalSet _intervalSet) {
        // FOR NOW THIS PRESUMES THE FIRST NOTE IS THE ROOT NOTE
        // EVENTUALLY CYCLE THROUGH ALL NOTES AS THE ROOT NOTE
        // WHEN SEARCHING
        Collection allScaleTypes = scaleTypes.values();

        for (Object currentScaleType : allScaleTypes) {
            if (currentScaleType.equals(_intervalSet)) {
                //_intervalSet.setName(((IntervalSet) currentScaleType).getName());
                //_intervalSet.setShortName(((IntervalSet) currentScaleType).getShortName());
                return (ScaleType) currentScaleType;
            }
        }

        // THE IntervalSet IS NOT A KNOWN SCALE
        //_intervalSet.setName("Unknown");
        //_intervalSet.setShortName("Unk");
        return null;
    }
}
